import * as child_process from 'child_process';
import * as vscode from 'vscode';
import { getConfig } from './configManager';
import * as path from 'path';
import * as fs from 'fs';

export async function executeJar(projectPath: string): Promise<void> {
  const config = getConfig();

  const jarPath = path.join(__dirname, '../CKGConstruction-1.0-SNAPSHOT.jar');
  const neo4jUrl = config.neo4j.serverUrl;
  const neo4jUser = config.neo4j.serverUser;
  const neo4jPassword = config.neo4j.serverPassword;

  if (!fs.existsSync(jarPath)) {
    vscode.window.showErrorMessage('Bundled CKGConstruction-1.0-SNAPSHOT.jar is missing. Try reinstalling the extension.');
    return;
  }

  if (!neo4jUrl || !neo4jUser || !neo4jPassword) {
    vscode.window.showErrorMessage('Please update config/userConfig.json with the Neo4j connection settings before generating the knowledge graph.');
    return;
  }

  // 设置日志目录为插件工作目录下的 logs 文件夹
  const extensionLogDir = path.join(__dirname, '../../logs');
  if (!fs.existsSync(extensionLogDir)) {
    fs.mkdirSync(extensionLogDir, { recursive: true });
  }

  const logPath = path.join(extensionLogDir, 'ckg.log'); // 指定日志文件路径
  // 使用绝对路径并确保正确转义
  const normalizedLogPath = path.resolve(logPath);
  const command = `java`;
  const args = [
    `-Dlog.path=${normalizedLogPath}`,
    `-jar`,
    jarPath,
    `-p`,
    projectPath,
    `-u`,
    neo4jUrl,
    `-n`,
    neo4jUser,
    `-w`,
    neo4jPassword,
  ];

  try {
    vscode.window.showInformationMessage('Preparing project and generating knowledge graph...');

    // 创建输出通道
    const outputChannel = vscode.window.createOutputChannel('Knowledge Graph Generation');
    outputChannel.show(true);

    const mvnCommand = process.platform === 'win32' ? 'mvn.cmd' : 'mvn';
    await runProcess(mvnCommand, ['clean', 'compile'], projectPath, outputChannel, 'mvn clean compile');
    await runProcess(mvnCommand, ['dependency:copy-dependencies'], projectPath, outputChannel, 'mvn dependency:copy-dependencies');
    await runProcess(command, args, undefined, outputChannel, 'Generate Knowledge Graph');

    vscode.window.showInformationMessage('Knowledge graph generated successfully!');
  } catch (err: any) {
    vscode.window.showErrorMessage(`Failed to generate knowledge graph: ${err.message || err}`);
  }
}

function runProcess(
  command: string,
  args: string[],
  cwd: string | undefined,
  outputChannel: vscode.OutputChannel,
  stepDescription: string
): Promise<void> {
  return new Promise((resolve, reject) => {
    outputChannel.appendLine(`\n[${stepDescription}] $ ${command} ${args.join(' ')}`);
    const proc = child_process.spawn(command, args, {
      cwd,
      shell: process.platform === 'win32',
    });

    proc.stdout.on('data', (data) => {
      outputChannel.append(data.toString());
    });

    proc.stderr.on('data', (data) => {
      outputChannel.append(`[ERROR] ${data.toString()}`);
    });

    proc.on('close', (code) => {
      if (code === 0) {
        outputChannel.appendLine(`[${stepDescription}] completed successfully.`);
        resolve();
      } else {
        reject(new Error(`${stepDescription} failed with exit code ${code}`));
      }
    });

    proc.on('error', (err) => {
      reject(err);
    });
  });
}
